#include "ha_can.h"
#include "string.h"

static uint8_t realdata[maxcnt] = {0};



void can_init(void)
{
	gpio_init_type gpio_init_struct;
	can_base_type can_base_struct;
	can_baudrate_type can_baudrate_struct;
	can_filter_init_type can_filter_init_struct;
	
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, TRUE);

	gpio_default_para_init(&gpio_init_struct);

	/* can tx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
	gpio_init_struct.gpio_pins = GPIO_PINS_12;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_init_struct);

	/* can rx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_11;
	gpio_init_struct.gpio_pull = GPIO_PULL_UP;
	gpio_init(GPIOA, &gpio_init_struct);
	
	/* can base init */
	can_default_para_init(&can_base_struct);
	can_base_struct.mode_selection = CAN_MODE_COMMUNICATE;
	can_base_struct.ttc_enable = FALSE;
	can_base_struct.aebo_enable = TRUE;
	can_base_struct.aed_enable = TRUE;
	can_base_struct.prsf_enable = FALSE;
	can_base_struct.mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED;
	can_base_struct.mmssr_selection = CAN_SENDING_BY_ID;
	can_base_init(CAN1, &can_base_struct);

	/* can baudrate, set baudrate = pclk/(baudrate_div *(1 + bts1_size + bts2_size)) */
	/* 50k	*/
	can_baudrate_struct.baudrate_div = 200;
	can_baudrate_struct.rsaw_size = CAN_RSAW_3TQ;
	can_baudrate_struct.bts1_size = CAN_BTS1_8TQ;
	can_baudrate_struct.bts2_size = CAN_BTS2_3TQ;
	can_baudrate_set(CAN1, &can_baudrate_struct);
	
	/* can filter 0 config */
	can_filter_init_struct.filter_activate_enable = TRUE;
	can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_LIST;
	can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0;
	can_filter_init_struct.filter_number = 0;
	can_filter_init_struct.filter_bit = CAN_FILTER_32BIT;
	can_filter_init_struct.filter_id_high = 0x10<<5;  /* standard identifier is 11 bit */
	can_filter_init_struct.filter_id_low = 0;
	can_filter_init_struct.filter_mask_high = 0x11<<5;/* standard identifier is 11 bit */
	can_filter_init_struct.filter_mask_low = 0;
	can_filter_init(CAN1, &can_filter_init_struct);
	
	/* can filter 1 config */
	can_filter_init_struct.filter_activate_enable = TRUE;
	can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_LIST;
	can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0;
	can_filter_init_struct.filter_number = 1;
	can_filter_init_struct.filter_bit = CAN_FILTER_32BIT;
	can_filter_init_struct.filter_id_high = 0xfe<<5;  /* standard identifier is 11 bit */
	can_filter_init_struct.filter_id_low = 0;
	can_filter_init_struct.filter_mask_high = 0xff<<5;/* standard identifier is 11 bit */
	can_filter_init_struct.filter_mask_low = 0;
	can_filter_init(CAN1, &can_filter_init_struct);
	
	/* can filter 2 config */
	can_filter_init_struct.filter_activate_enable = TRUE;
	can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_LIST;
	can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0;
	can_filter_init_struct.filter_number = 2;
	can_filter_init_struct.filter_bit = CAN_FILTER_32BIT;
	can_filter_init_struct.filter_id_high = 0xfa<<5;  /* standard identifier is 11 bit */
	can_filter_init_struct.filter_id_low = 0;
	can_filter_init_struct.filter_mask_high = 0xfb<<5;/* standard identifier is 11 bit */
	can_filter_init_struct.filter_mask_low = 0;
	can_filter_init(CAN1, &can_filter_init_struct);
	
	/* can interrupt config */
	nvic_irq_enable(CAN1_SE_IRQn, 0x01, 0x00);
	nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn, 0x01, 0x00);
	can_interrupt_enable(CAN1, CAN_RF0MIEN_INT, TRUE);

	/* error interrupt enable */
	can_interrupt_enable(CAN1, CAN_ETRIEN_INT, TRUE);
	can_interrupt_enable(CAN1, CAN_EOIEN_INT, TRUE);
}

/**
  *  @brief  can1 interrupt function rx0
  *  @param  none
  *  @retval none
  */
void USBFS_L_CAN1_RX0_IRQHandler (void)
{
	can_rx_message_type rx_message;
	if(can_flag_get(CAN1,CAN_RF0MN_FLAG) != RESET)
	{
		can_message_receive(CAN1, CAN_RX_FIFO0, &rx_message);
		switch(rx_message.standard_id){
			case 0x10:
				realdata[ser_mode] = rx_message.data[2];
				realdata[run_dir] = rx_message.data[3];
				realdata[acd_num] = rx_message.data[4];
				realdata[comfort] = rx_message.data[5];
				realdata[dis_floor] = rx_message.data[6];
			break;
			case 0x11:
				realdata[phy_floor] = rx_message.data[0];
				realdata[speed_h] = rx_message.data[1];
				realdata[speed_l] = rx_message.data[2];
				realdata[safe_bit] = rx_message.data[5];
				realdata[mdoor_bit] = rx_message.data[6];
				realdata[sdoor_bit] = rx_message.data[7];
			break;
			case 0xfe:
				realdata[m1_8_incall] = rx_message.data[1];
				realdata[m6_16_incall] = rx_message.data[2];
				realdata[m17_24_incall] = rx_message.data[3];
				realdata[m25_32_incall] = rx_message.data[4];
			break;
			case 0xff:
				realdata[m33_40_incall] = rx_message.data[4];
				realdata[m41_48_incall] = rx_message.data[5];
			break;
			case 0xfa:
				realdata[s1_8_incall] = rx_message.data[1];
				realdata[s6_16_incall] = rx_message.data[2];
				realdata[s17_24_incall] = rx_message.data[3];
				realdata[s25_32_incall] = rx_message.data[4];
			break;
			case 0xfb:
				realdata[s33_40_incall] = rx_message.data[4];
				realdata[s41_48_incall] = rx_message.data[5];
			break;
			default:
				rx_message.data[4] = 1;
			break;
		}
	}
}

/**
  *  @brief  can1 interrupt function se
  *  @param  none
  *  @retval none
  */
void CAN1_SE_IRQHandler(void)
{
	__IO uint32_t err_index = 0;
	if(can_flag_get(CAN1,CAN_ETR_FLAG) != RESET)
	{
		err_index = CAN1->ests & 0x70;
		can_flag_clear(CAN1, CAN_ETR_FLAG);
		/* error type is stuff error */
		if(err_index == 0x00000010)
		{
			/* when stuff error occur: in order to ensure communication normally,
			user must restart can or send a frame of highest priority message here */
		}
	}
}

/**
  *  @brief  can transmit data
  *  @param  none
  *  @retval none
  */
void can_transmit_data(uint16_t len,uint8_t * buf)
{
	can_tx_message_type tx_message_struct;
	
	/* transmit FILTER_STD_ID1 */
	tx_message_struct.standard_id = 0x401;
	tx_message_struct.extended_id = 0;
	tx_message_struct.id_type = CAN_ID_STANDARD;
	tx_message_struct.frame_type = CAN_TFT_DATA;
	tx_message_struct.dlc = len;
	tx_message_struct.data[0] = buf[0];
	tx_message_struct.data[1] = buf[1];
	tx_message_struct.data[2] = buf[2];
	tx_message_struct.data[3] = buf[3];
	tx_message_struct.data[4] = buf[4];
	tx_message_struct.data[5] = buf[5];
	tx_message_struct.data[6] = buf[6];
	tx_message_struct.data[7] = buf[7];
	can_message_transmit(CAN1, &tx_message_struct);
}

/**
  *  @brief  can transmit data
  *  @param  none
  *  @retval none
  */
void can_get_data(uint8_t * buf)
{
	realdata[data_len] = 23;
	memcpy(buf,realdata,maxcnt);
}


